﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using SimpleExpressionEvaluator.Utilities;

namespace SimpleExpressionEvaluator.Tests.Utilities
{
    [TestFixture]
    public class ReflectionTestFixture
    {
        [Test]
        public void Can_Parse_Single_Element_Instance_Property_Path()
        {
            PropertyPath path = PropertyPath.Parse(typeof (DateTime), "hour");
            Assert.That(path.Evaluate(DateTime.Now), Is.EqualTo(DateTime.Now.Hour));
        }

        [Test]
        public void Can_Parse_Multi_Element_Instance_Property_Path()
        {
            PropertyPath path = PropertyPath.Parse(typeof (DateTime), "date.hour");
            Assert.That(path.Evaluate(DateTime.Now), Is.EqualTo(DateTime.Now.Date.Hour));
        }

        [Test]
        public void Can_Parse_Static_Property()
        {
            PropertyPath path = PropertyPath.Parse(typeof (DateTime), "today");
            Assert.That(path.Evaluate(null), Is.EqualTo(DateTime.Today));
        }

        [Test]
        public void Null_Target_For_Instance_Prop_Returns_Null()
        {
            PropertyPath path = PropertyPath.Parse(typeof (DateTime), "hour");
            Assert.IsNull(path.Evaluate(null));
        }

        [Test]
        public void Assert_Bad_Path_Returns_Null()
        {
            PropertyPath path = PropertyPath.Parse(typeof (DateTime), "hour.hour");
            Assert.IsNull(path);
        }

        [Test]
        public void Extension_Will_Evaluate_Prop_Path()
        {
            Assert.That(DateTime.Now.EvaluatePropertyPath("hour"), Is.EqualTo(DateTime.Now.Hour));
        }

        [Test]
        public void Extension_Will_Parse_Prop_Path()
        {
            PropertyPath path = DateTime.Now.ParsePropertyPath("hour");
            Assert.That(path.Evaluate(DateTime.Now), Is.EqualTo(DateTime.Now.Hour));
        }

        [Test]
        public void PropertyPathWillEvaluateFieldsAndProperties()
        {
            var data = new TestDataObjectWithFields
                           {
                               InnerObject = new TestDataObjectWithFields {IntegerProperty = 4}
                           };
            PropertyPath path = data.ParsePropertyPath("InnerObject.IntegerProperty");
            Assert.That(path.Evaluate(data), Is.EqualTo(4));
        }

        public class TestDataObjectWithFields
        {
            public TestDataObjectWithFields InnerObject;

            public int IntegerProperty { get; set; }
        }

    }
}
